网络消息

除了高级命令和RPC调用功能外,还可以发送原始网络消息。

有一个名为MessageBase的类可以扩展为可串行化的网络消息类。该类具有序列化和反序列化功能,可以使用Writer和Reader对象。开发人员可以自己实现这些功能,也可以依赖由网络系统自动创建的代码生成的实现。基类看起来像这样:

    public abstract class MessageBase
    {
        // De-serialize the contents of the reader into this message
        public virtual void Deserialize(NetworkReader reader) {}

        // Serialize the contents of this message into the writer
        public virtual void Serialize(NetworkWriter writer) {}
    }

消息类可以包含基本类型,结构体,数组和大多数常见Unity Engine类型(如Vector3)的成员。他们不能包含复杂类或泛型容器的成员。

有一些常用类型的网络消息的内置消息类别:

    • EmptyMessage
    • StringMessage
    • IntegerMessage

要发送消息,NetworkClientNetworkServerNetworkConnection类上都有Send()函数,它们的工作方式相同。他们接收消息ID和从MessageBase派生的消息对象。下面的代码展示了如何使用其中一个内置的消息类来发送和处理消息:

    using UnityEngine;
    using UnityEngine.Networking;
    using UnityEngine.Networking.NetworkSystem;

    public class Begin : NetworkBehaviour
    {
        const short MyBeginMsg = 1002;

        NetworkClient m_client;

        public void SendReadyToBeginMessage(int myId)
        {
            var msg = new IntegerMessage(myId);
            m_client.Send(MyBeginMsg, msg);
        }

        public void Init(NetworkClient client)
        {
            m_client = client;
            NetworkServer.RegisterHandler(MyBeginMsg, OnServerReadyToBeginMessage);
        }

        void OnServerReadyToBeginMessage(NetworkMessage netMsg)
        {
            var beginMessage = netMsg.ReadMessage<IntegerMessage>();
            Debug.Log("received OnServerReadyToBeginMessage " + beginMessage.value);
        }
    }

声明自定义网络消息类并使用它:

    using UnityEngine;
    using UnityEngine.Networking;

    public class Scores : MonoBehaviour
    {
        NetworkClient myClient;

        public class MyMsgType {
            public static short Score = MsgType.Highest + 1;
        }

        public class ScoreMessage : MessageBase
        {
            public int score;
            public Vector3 scorePos;
            public int lives;
        }

        public void SendScore(int score, Vector3 scorePos, int lives)
        {
            ScoreMessage msg = new ScoreMessage();
            msg.score = score;
            msg.scorePos = scorePos;
            msg.lives = lives;

            NetworkServer.SendToAll(MyMsgType.Score, msg);
        }

        // Create a client and connect to the server port
        public void SetupClient()
        {
            myClient = new NetworkClient();
            myClient.RegisterHandler(MsgType.Connect, OnConnected);
            myClient.RegisterHandler(MyMsgType.Score, OnScore);
            myClient.Connect("127.0.0.1", 4444);
        }

        public void OnScore(NetworkMessage netMsg)
        {
            ScoreMessage msg = netMsg.ReadMessage<ScoreMessage>();
            Debug.Log("OnScoreMessage " + msg.score);
        }

        public void OnConnected(NetworkMessage netMsg)
        {
            Debug.Log("Connected to server");
        }
    }

请注意,例如,此源代码中没有ScoreMessage类的序列化代码。序列化函数的主体是为这个类自动生成的。

错误消息类

Thre也是一个派生自MessageBase的ErrorMessage类。该类传递给客户端和服务器上的错误回调。

ErrorMessage类中的errorCode对应于Networking.NetworkError枚举。

    class MyClient
    {
        NetworkClient client;

        void Start()
        {
            client = new NetworkClient();
            client.RegisterHandler(MsgType.Error, OnError);
        }

        void OnError(NetworkMessage netMsg)
        {
            var errorMsg = netMsg.ReadMessage<ErrorMessage>();
            Debug.Log("Error:" + errorMsg.errorCode);
        }
    }

🔚